/*
* Copyright (C) 2006, 2007 Dennis Hunziker, Ueli Kistler
* Copyright (C) 2007 Reto Schuettel, Robin Stocker
*
* IFS Institute for Software, HSR Rapperswil, Switzerland
*
*/
package org.python.pydev.refactoring.coderefactoring.extractlocal;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.python.pydev.core.log.Log;
import org.python.pydev.parser.jython.ParseException;
import org.python.pydev.parser.jython.TokenMgrError;
import org.python.pydev.parser.jython.ast.Expr;
import org.python.pydev.parser.jython.ast.Module;
import org.python.pydev.parser.jython.ast.exprType;
import org.python.pydev.parser.jython.ast.stmtType;
import org.python.pydev.refactoring.ast.adapters.AbstractScopeNode;
import org.python.pydev.refactoring.ast.adapters.ModuleAdapter;
import org.python.pydev.refactoring.ast.visitors.VisitorFactory;
import org.python.pydev.refactoring.core.base.AbstractPythonRefactoring;
import org.python.pydev.refactoring.core.base.RefactoringInfo;
import org.python.pydev.refactoring.core.change.IChangeProcessor;
import org.python.pydev.refactoring.core.validator.NameValidator;
import org.python.pydev.refactoring.messages.Messages;
import org.python.pydev.refactoring.utils.ListUtils;
import com.aptana.shared_core.structure.Tuple;
public class ExtractLocalRefactoring extends AbstractPythonRefactoring {
private ExtractLocalRequestProcessor requestProcessor;
public ExtractLocalRefactoring(RefactoringInfo info) {
super(info);
this.requestProcessor = new ExtractLocalRequestProcessor(info);
}
@Override
protected List<IChangeProcessor> getChangeProcessors() {
IChangeProcessor changeProcessor = new ExtractLocalChangeProcessor(getName(), this.info, this.requestProcessor);
return ListUtils.wrap(changeProcessor);
}
@Override
public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
List<Tuple<ITextSelection, ModuleAdapter>> selections = new LinkedList<Tuple<ITextSelection, ModuleAdapter>>();
/* Use different approaches to find a valid selection */
selections
.add(new Tuple<ITextSelection, ModuleAdapter>(info.getUserSelection(), info.getParsedUserSelection()));
selections.add(new Tuple<ITextSelection, ModuleAdapter>(info.getExtendedSelection(), info
.getParsedExtendedSelection()));
selections.add(new Tuple<ITextSelection, ModuleAdapter>(info.getUserSelection(),
getParsedMultilineSelection(info.getUserSelection())));
/* Find a valid selection */
ITextSelection selection = null;
exprType expression = null;
for (Tuple<ITextSelection, ModuleAdapter> s : selections) {
/* Is selection valid? */
if (s != null) {
expression = extractExpression(s.o2);
selection = s.o1;
if (expression != null) {
break;
}
}
}
/* No valid selections found, report error */
if (expression == null) {
status.addFatalError(Messages.extractLocalNoExpressionSelected);
}
AbstractScopeNode<?> scopeAdapter = info.getModuleAdapter().getScopeAdapter(selection);
requestProcessor.setDuplicates(scopeAdapter.getDuplicates(selection, expression));
requestProcessor.setSelection(selection);
requestProcessor.setExpression(expression);
return status;
}
private ModuleAdapter getParsedMultilineSelection(ITextSelection selection) {
String source = selection.getText();
source = source.replaceAll("\n", "");
source = source.replaceAll("\r", "");
try {
ModuleAdapter node = VisitorFactory.createModuleAdapter(null, null, new Document(source), null,
info.getVersionProvider());
return node;
} catch (TokenMgrError e) {
return null;
} catch (ParseException e) {
return null;
} catch (Throwable e) {
Log.log(e);
return null;
}
}
private exprType extractExpression(ModuleAdapter node) {
if (node == null) {
return null;
}
Module astNode = node.getASTNode();
if (astNode == null) {
return null;
}
stmtType[] body = astNode.body;
if (body.length > 0 && body[0] instanceof Expr) {
Expr expr = (Expr) body[0];
return expr.value;
}
return null;
}
@Override
public String getName() {
return Messages.extractLocalLabel;
}
public ExtractLocalRequestProcessor getRequestProcessor() {
return requestProcessor;
}
/**
* Checks if a given variable name is valid or not. Using invalid
* identifiers (e.g. special chars) or already used variable names
* aren't allowed and would result in a fatal status
*
* @param variableName
* @return status
*/
public RefactoringStatus checkVarName(String variableName) {
RefactoringStatus status = new RefactoringStatus();
NameValidator nameValidator = new NameValidator(status, info.getScopeAdapter());
nameValidator.validateVariableName(variableName);
nameValidator.validateUniqueVariable(variableName);
return status;
}
}